/**
* Copyright (C), 2018-2030, Hisilicon Tech. Co., Ltd.
* All rights reserved.
*
* @file      kfifo.c
* @brief     mcu uart file
* @author    xxxxx develop team
* @date      2019.01.05
*/
#include "kfifo.h"

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */


void __kfifo_init(struct kfifo* fifo, HI_U8* pBuf, HI_U16 bufSize)
{
    int i = 0;

    for (i = 0; i < bufSize; i++)
    {
        pBuf[i] = 0;
    }

    fifo->buffer = pBuf;
    fifo->size = bufSize / sizeof(HI_U8);
    fifo->in = fifo->out = 0;
}


unsigned int  __kfifo_len(struct kfifo* fifo)
{
    unsigned int   in, out, size;

    in   = fifo->in;
    out  = fifo->out;
    size = fifo->size;

    return (in >= out) ? (in - out) : (size - out + in);
}



unsigned int __kfifo_put(struct kfifo* fifo, HI_U8* buffer, HI_U16 len)
{
    unsigned int   tmpLen;
    unsigned int   in, out;
    unsigned int   emptyCnt;

    in  = fifo->in;
    out = fifo->out;

    emptyCnt = (in >= out) ? (fifo->size - in + out) : (out - in);

    if (len > emptyCnt)
    {
        return 0;
    }

    /* first put the data starting from fifo->in to buffer end */
    tmpLen = MIN(len, fifo->size - in);
    memcpy(fifo->buffer + in, buffer, tmpLen);

    /* then put the rest (if any) at the beginning of the buffer */
    memcpy(fifo->buffer, buffer + tmpLen, len - tmpLen);

    fifo->in += len;
    fifo->in &= fifo->size - 1;

    return len;
}




void __kfifo_put_singlebyte(struct kfifo* fifo, HI_U8 data)
{
    fifo->buffer[(fifo->in++) & (fifo->size - 1)] = data;

    fifo->in &= fifo->size - 1;
}




unsigned int __kfifo_get(struct kfifo* fifo, HI_U8* buffer, HI_U16 len)
{
    unsigned int   tmpLen;
    unsigned int   out, size;

    out = fifo->out;
    size = fifo->size;

    if (len > __kfifo_len(fifo))
    {
        return 0;
    }

    /* first get the data from fifo->out until the end of the buffer */
    tmpLen = MIN(len, size - out );
    memcpy(buffer, fifo->buffer + out, tmpLen);

    /* then get the rest (if any) from the beginning of the buffer */
    memcpy(buffer + tmpLen, fifo->buffer, len - tmpLen);

    fifo->out += len;
    fifo->out &= fifo->size - 1;

    return len;
}

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */
